package com.whiteape.book.core.manager;

import com.whiteape.book.model.bo.CategoryDetailBo;
import com.whiteape.book.model.dto.CollectionMediaBean;
import com.whiteape.book.model.dto.SiteSourceBean;
import com.whiteape.book.model.gen.CategoryDetailBoDao;
import com.whiteape.book.model.gen.DaoSession;
import com.whiteape.book.model.gen.SiteSourceBeanDao;
import com.whiteape.book.model.gen.SiteSourceCategoryBeanDao;
import com.whiteape.book.model.type.MediaType;
import com.whiteape.book.net.RetrofitHelper;
import com.whiteape.book.utils.DaoDbHelper;
import com.whiteape.book.utils.FileUtils;
import com.whiteape.book.utils.GsonUtils;
import com.whiteape.book.utils.RxUtils;
import com.whiteape.book.utils.StringUtils;
import com.whiteape.book.utils.URLUtils;

import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import io.reactivex.Single;

public class SiteSourceManager {

    private static volatile SiteSourceManager sInstance;
    private SiteSourceBeanDao siteSourceBeanDao;
    private DaoSession daoSession;

    private SiteSourceManager() {
        daoSession = DaoDbHelper.getInstance().getSession();
        siteSourceBeanDao = daoSession.getSiteSourceBeanDao();
    }

    public static SiteSourceManager getInstance() {
        if (sInstance == null) {
            synchronized (MediaStorageManager.class) {
                if (sInstance == null) {
                    sInstance = new SiteSourceManager();
                }
            }

        }
        return sInstance;
    }

    public void saveSiteSource(SiteSourceBean siteSourceBean) {
        daoSession.insertOrReplace(siteSourceBean);
    }

    public SiteSourceBean getSiteSource(String siteUrl) {
        return siteSourceBeanDao.load(siteUrl);
    }

    public void deleteSiteSource(List<SiteSourceBean> siteSourceBeanList) {
        siteSourceBeanDao.deleteInTx(siteSourceBeanList);
    }

    public void deleteSiteSourceCategory(Set<String> hostUrlList) {
        daoSession.getSiteSourceCategoryBeanDao().queryBuilder()
                .where(SiteSourceCategoryBeanDao.Properties.SiteHostUrl.in(hostUrlList))
                .buildDelete().executeDeleteWithoutDetachingEntities();
    }

    public void deleteSiteCategoryDetailBo(Set<String> siteHostUrlSet) {

        for (String siteHostUrl : siteHostUrlSet) {
            daoSession.getCategoryDetailBoDao().queryBuilder()
                    .where(CategoryDetailBoDao.Properties.CategoryUrl.like(siteHostUrl + "%"))
                    .buildDelete().executeDeleteWithoutDetachingEntities();
        }
    }

    public Single<Boolean> deleteSiteSourceInRx(List<SiteSourceBean> siteSourceBeanList) {
        return Single.create(emitter -> {
            //校验是否书架中有正在使用的网源，有的话不能删除
            Set<String> deletedItemUrlSet = new HashSet<>();
            for (SiteSourceBean siteSourceBean : siteSourceBeanList) {
                deletedItemUrlSet.add(siteSourceBean.getSiteHostUrl());
            }
            List<CollectionMediaBean> mediaList = MediaStorageManager.getInstance().getShelfBookList();
            for (CollectionMediaBean media : mediaList) {
                media.__setDaoSession(DaoDbHelper.getInstance().getSession());
                String siteSourceBeanUrl = media.getSiteSourceBean().getSiteHostUrl();
                if (deletedItemUrlSet.contains(siteSourceBeanUrl)) {
                    emitter.onError(new Throwable("有书源正在使用中(书架中的部分小说、漫画在用此网源)，无法删除"));
                    return;
                }
            }

            siteSourceBeanDao.deleteInTx(siteSourceBeanList);
            deleteSiteSourceCategory(deletedItemUrlSet);
            deleteSiteCategoryDetailBo(deletedItemUrlSet);
            emitter.onSuccess(true);
        });
    }

    public List<SiteSourceBean> getSiteSourceAll() {
        return siteSourceBeanDao.loadAll();
    }

    public List<SiteSourceBean> getSiteSourceExclude(Set<String> excludeSiteHostUrl) {
        return siteSourceBeanDao.queryBuilder().where(SiteSourceBeanDao.Properties.SiteHostUrl.notIn(excludeSiteHostUrl))
                .build().list();
    }

    public Single<List<SiteSourceBean>> getSiteSourceAllInRx() {
        return Single.create(emitter -> {
            List<SiteSourceBean> result = siteSourceBeanDao.loadAll();
            if (result == null) {
                emitter.onError(new Throwable("No Data"));
            } else {
                emitter.onSuccess(result);
            }
        });
    }

    public List<SiteSourceBean> getSiteSourceWithMediaType(int mediaType) {
        return siteSourceBeanDao.queryBuilder().where(
                SiteSourceBeanDao.Properties.SiteType.eq(mediaType)
        ).build().list();
    }

    /**
     * 过滤查询
     *
     * @param word
     * @return
     */
    public List<SiteSourceBean> filterSiteSourceAll(String word) {
        return siteSourceBeanDao.queryBuilder().whereOr(
                SiteSourceBeanDao.Properties.SiteName.like("%" + word + "%"),
                SiteSourceBeanDao.Properties.Creator.like("%" + word + "%"),
//                SiteSourceBeanDao.Properties.SiteType.like("%" + word + "%"),
                SiteSourceBeanDao.Properties.SiteDesc.like("%" + word + "%")
        ).build().list();
    }

    public Single<List<SiteSourceBean>> filterSiteSourceAllInRx(String word) {
        return Single.create(emitter -> {
            emitter.onSuccess(filterSiteSourceAll(word));
        });
    }

    private int importSiteSourceByJsonLocally(String jsonStr) throws Exception {
        try {

            if (!StringUtils.isJsonFormat(jsonStr)) {
                return -1;
            }
            String str = jsonStr.trim();
            if (StringUtils.isJsonObjFormat(str)) {
                SiteSourceBean siteSourceBean = GsonUtils.string2Obj(str, SiteSourceBean.class);
                if (siteSourceBean.getEnabled() == null) {
                    siteSourceBean.setEnabled(true);
                }

                if (siteSourceBean.getPriority() == null) {
                    siteSourceBean.setPriority(0);
                }

                siteSourceBeanDao.insertOrReplace(siteSourceBean);
                return 1;
            } else if (StringUtils.isJsonArrFormat(str)) {
                List<SiteSourceBean> siteSourceBeanList = GsonUtils.string2List(str, SiteSourceBean.class);
                for (SiteSourceBean siteSourceBean : siteSourceBeanList) {
                    if (siteSourceBean.getEnabled() == null) {
                        siteSourceBean.setEnabled(true);
                    }
                    if (siteSourceBean.getPriority() == null) {
                        siteSourceBean.setPriority(1);
                    }
                }
                siteSourceBeanDao.insertOrReplaceInTx(siteSourceBeanList);
                return siteSourceBeanList.size();
            } else {
                return -1;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }

    }

    public Single<Integer> importSiteSourceByJson(String jsonStr) {

        return Single.create(emitter -> {
            try {
                int ret = importSiteSourceByJsonLocally(jsonStr);
                if (ret == -1) {
                    emitter.onError(new Throwable("格式不正确"));
                    return;
                }
                emitter.onSuccess(ret);
            } catch (Exception e) {
                e.printStackTrace();
                emitter.onError(e);
            }
        });
    }

    public Single<Integer> importSiteSourceByUrl(String url) {

        return RetrofitHelper.getInstance()
                .getHttpApiImpl(URLUtils.getBaseUrl(url))
                .get(url.trim(), new HashMap<>())
                .compose(RxUtils::toSimpleSingle)
                .flatMap(stringResponse -> importSiteSourceByJson(stringResponse.body()));
    }

    public Single<Integer> importSiteSource(String str) {
        if (StringUtils.isEmpty(str)) {
            return Single.create(emitter -> {
                emitter.onError(new Throwable("格式错误"));
            });
        }
        if (StringUtils.isUrlFormat(str)) {
            return importSiteSourceByUrl(str);
        } else {
            return importSiteSourceByJson(str);
        }

    }

    public Single<Integer> importSiteSource(File file) {
        String fileContent = FileUtils.getFileContent(file);
        return importSiteSource(fileContent);
    }

    //TODO 如果导入多个文件，这里我们要求必须是json格式的
    public Single<Integer> importSiteSource(List<File> fileList) {

        if (fileList != null && fileList.size() == 1) {
            return importSiteSource(fileList.get(0));
        }

        return Single.create(emitter -> {
            if (fileList == null || fileList.size() == 0) {
                emitter.onError(new Throwable("选择文件错误"));
                return;
            }
            int total = 0;
            for (File file : fileList) {
                String fileContent = FileUtils.getFileContent(file);
                try {
                    int ret = importSiteSourceByJsonLocally(fileContent);
                    total += ret;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            emitter.onSuccess(total);
        });

    }

}
